home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Games / Battleship ƒ / Code folder / Battleship.c next >
Encoding:
C/C++ Source or Header  |  1994-05-07  |  26.6 KB  |  1,362 lines  |  [TEXT/KAHL]

  1. #include    "Battleship.h"
  2.  
  3. /********/
  4. /* main */
  5. /********/
  6.  
  7. void    main ( void )
  8. {
  9.     short theAlert;
  10.     
  11.     ToolBoxInit ();
  12.     MenuBarInit ();
  13.     
  14.     HandleAppleChoice ( iAbout );
  15.     useColor = IsColour();
  16.  
  17.     WindowInit ();
  18.     PlaceEnemyShips ();
  19.     
  20.     NewGame ();
  21.     EventLoop ();
  22. }
  23.  
  24. /**************/
  25. /* ToolBoxInit*/
  26. /**************/
  27.  
  28. void    ToolBoxInit ( void )
  29. {
  30.     InitGraf ( &thePort );
  31.     InitFonts ();
  32.     InitWindows ();
  33.     InitMenus ();
  34.     TEInit ();
  35.     InitDialogs ( nil );
  36.     InitCursor ();
  37. }
  38.  
  39. /**************/
  40. /* WindowInit */
  41. /**************/
  42.  
  43. void    WindowInit ( void )
  44. {
  45.     if ( useColor )
  46.         youWindow = GetNewCWindow ( kYouWindowID, nil, kMoveToFront );
  47.     else
  48.         youWindow = GetNewWindow ( kYouWindowID, nil, kMoveToFront );
  49.     
  50.     if ( youWindow == nil )
  51.     {
  52.         SysBeep ( 10 );
  53.         ExitToShell ();
  54.     }
  55.     
  56.     SetWRefCon ( youWindow, (long) kYouWindowID );
  57.  
  58.     SetPort ( youWindow );
  59.     ShowWindow ( youWindow );
  60.  
  61.     if ( useColor )
  62.         enemyWindow = GetNewCWindow ( kEnemyWindowID, nil, kMoveToFront );
  63.     else
  64.         enemyWindow = GetNewWindow ( kEnemyWindowID, nil, kMoveToFront );
  65.     
  66.     if ( enemyWindow == nil )
  67.     {
  68.         SysBeep ( 10 );
  69.         ExitToShell ();
  70.     }
  71.     
  72.     SetWRefCon ( enemyWindow, (long) kEnemyWindowID );
  73.     SetPort ( enemyWindow );
  74.     ShowWindow ( enemyWindow );
  75. }
  76.  
  77.  
  78. /***************/
  79. /* MenuBarInit */
  80. /***************/
  81.  
  82. void    MenuBarInit ( void )
  83. {
  84.     Handle            menuBar;
  85.     MenuHandle        menu;
  86.     
  87.     menuBar = GetNewMBar ( kBaseResID );
  88.     SetMenuBar ( menuBar );
  89.     
  90.     menu = GetMHandle ( mApple );
  91.     AddResMenu ( menu, 'DRVR' );
  92.     
  93.     DrawMenuBar ();
  94.     
  95.     HandleSound ();
  96. }
  97.  
  98. /***************/
  99. /* HandleSound */
  100. /***************/
  101.  
  102. void    HandleSound ( void )
  103. {
  104.     MenuHandle    menuHandle;
  105.     
  106.     menuHandle = GetMHandle ( mOptions );
  107.     
  108.     
  109.     if ( gHasSound )
  110.     {
  111.         CheckItem ( menuHandle, iSound, kRemoveCheckMark );
  112.         gHasSound = !gHasSound;
  113.     }
  114.     else
  115.     {
  116.         CheckItem ( menuHandle, iSound, kAddCheckMark );
  117.         gHasSound = !gHasSound;
  118.     }
  119. }
  120.  
  121. /*************/
  122. /* EventLoop */
  123. /*************/
  124.  
  125. void    EventLoop ( void )
  126. {
  127.     EventRecord    event;
  128.     int            theAlert;
  129.     
  130.     gDone = false;
  131.     while ( gDone == false )
  132.     {
  133.         if ( WaitNextEvent ( everyEvent, &event, MAXLONG, nil ) )
  134.             DoEvent ( &event );
  135.  
  136.         if ( enemyCount >= 17 ) /* you win! */
  137.         {
  138.             SelectWindow ( enemyWindow );
  139.             SetPort ( enemyWindow );
  140.             DrawDots ( enemy );
  141.             
  142.             ParamText( kCongratulationsStr, kYouWinStr, "\p", "\p" );
  143.             theAlert = Alert ( kBaseResID + 1, nil );
  144.             if ( theAlert == iPlayAgainCheckBox )
  145.                 NewGame ();
  146.             else
  147.                 gDone = TRUE;
  148.         }
  149.         else if ( ( gYouHasGone ) && ( !gDone ) )
  150.         {
  151.             PickEnemyShot ();
  152.             gYouHasGone = !gYouHasGone;
  153.         }
  154.         if ( youCount >= 17 ) /* computer wins! */
  155.         {
  156.             SelectWindow ( enemyWindow );
  157.             SetPort ( enemyWindow );
  158.             DrawDots ( enemy );
  159.             
  160.             ParamText( kSorryStr, kYouLoseStr, "\p", "\p" );
  161.             theAlert = Alert ( kBaseResID + 1, nil );
  162.             if ( theAlert == iPlayAgainCheckBox )
  163.                 NewGame ();
  164.             else
  165.                 gDone = TRUE;
  166.         }
  167.     }
  168. }
  169.  
  170.  
  171. /***********/
  172. /* DoEvent */
  173. /***********/
  174.  
  175. void    DoEvent ( EventRecord *eventPtr )
  176. {
  177.     Boolean    becomingActive;
  178.     char    theChar;
  179.     
  180.     switch ( eventPtr->what )
  181.     {
  182.         case mouseDown:
  183.             HandleMouseDown ( eventPtr );
  184.             break;
  185.         case keyDown:
  186.         case autoKey:
  187.             theChar = eventPtr->message & charCodeMask;
  188.             if ( (eventPtr->modifiers & cmdKey) != 0 )
  189.                 HandleMenuChoice ( MenuKey ( theChar ) );
  190.             break;
  191.         case updateEvt:
  192.             DoUpdate ( eventPtr );
  193.             break;
  194.         case activateEvt:
  195.             becomingActive = ( ( eventPtr->modifiers &activeFlag ) == activeFlag );
  196.             break;
  197.     }
  198. }
  199.  
  200. /*******************/
  201. /* HandleMouseDown */
  202. /*******************/
  203.  
  204. void    HandleMouseDown ( EventRecord *eventPtr )
  205. {
  206.     WindowPtr    window;
  207.     short int    thePart;
  208.     long        menuChoice;
  209.     
  210.     thePart = FindWindow ( eventPtr->where, &window );
  211.     
  212.     switch ( thePart )
  213.     {
  214.         case inMenuBar:
  215.             menuChoice = MenuSelect ( eventPtr->where );
  216.             HandleMenuChoice ( menuChoice );
  217.             break;
  218.         case inSysWindow:
  219.             SystemClick ( eventPtr, window );
  220.             break;
  221.         case inContent:
  222.             SelectWindow ( window );
  223.             if ( GetWRefCon ( window ) == kEnemyWindowID )
  224.             {
  225.                 SetPort ( window );
  226.                 CheckPoint ( eventPtr->where );
  227.             }
  228.             break;
  229.         case inDrag:
  230.             DragWindow ( window, eventPtr->where, &screenBits.bounds );
  231.             break;
  232.         case inGoAway:
  233.             if ( TrackGoAway ( window, eventPtr->where ) )
  234.                 gDone = true;
  235.             break;
  236.     }
  237. }
  238.  
  239. /************/
  240. /* DoUpdate */
  241. /************/
  242.  
  243. void    DoUpdate ( EventRecord *eventPtr )
  244. {
  245.     WindowPtr    window;
  246.     
  247.     window = ( WindowPtr ) eventPtr->message;
  248.     
  249.     BeginUpdate ( window );
  250.     
  251.     if ( GetWRefCon ( window ) == kEnemyWindowID )
  252.     {
  253.         SetPort ( window );
  254.         DrawDots ( enemy );
  255.     }
  256.  
  257.     if ( GetWRefCon ( window ) == kYouWindowID )
  258.     {
  259.         SetPort ( window );
  260.         DrawDots ( you );
  261.     }
  262.     
  263.     EndUpdate ( window );
  264. }
  265.  
  266. /********************/
  267. /* HandleMenuChoice */
  268. /********************/
  269.  
  270. void    HandleMenuChoice ( long menuChoice )
  271. {
  272.     short    menu;
  273.     short    item;
  274.     
  275.     if ( menuChoice != 0 )
  276.     {
  277.         menu = HiWord ( menuChoice );
  278.         item = LoWord ( menuChoice );
  279.         
  280.         switch ( menu )
  281.         {
  282.             case mApple:
  283.                 HandleAppleChoice ( item );
  284.                 break;
  285.             case mFile:
  286.                 HandleFileChoice ( item );
  287.                 break;
  288.             case mOptions:
  289.                 HandleOptionsChoice ( item );
  290.         }
  291.         
  292.         HiliteMenu ( 0 );
  293.     }
  294. }
  295.  
  296. /********************/
  297. /* HandleAppleChoice*/
  298. /********************/
  299.  
  300. void    HandleAppleChoice ( short item )
  301. {
  302.     MenuHandle    appleMenu;
  303.     Str255        accName;
  304.     short        accNumber, theAlert = 0;
  305.     
  306.     switch ( item )
  307.     {
  308.         case iAbout:
  309.             ParamText( kVersionNumberStr, "\p", "\p", "\p" );
  310.             theAlert = Alert ( kBaseResID + 3, nil );
  311.             if ( theAlert == 2 )
  312.                 Alert ( kBaseResID + 4, nil );
  313.             break;
  314.         default:
  315.             appleMenu = GetMHandle ( mApple );
  316.             GetItem ( appleMenu, item, accName );
  317.             accNumber = OpenDeskAcc ( accName );
  318.             break;
  319.     }
  320. }
  321.  
  322. /********************/
  323. /* HandleFileChoice */
  324. /********************/
  325.  
  326. void     HandleFileChoice ( short item )
  327. {
  328.     switch ( item )
  329.     {
  330.         case iQuit:
  331.             gDone = TRUE;
  332.             break;
  333.         case iNew:
  334.             NewGame ();
  335.             break;
  336.     }
  337. }
  338.  
  339. /***********************/
  340. /* HandleOptionsChoice */
  341. /***********************/
  342.  
  343. void    HandleOptionsChoice ( short item )
  344. {
  345.     switch ( item )
  346.     {
  347.         case iSound:
  348.             HandleSound ();
  349.             break;
  350.     }
  351. }
  352.  
  353. /***********/
  354. /* NewGame */
  355. /***********/
  356.  
  357. void    NewGame ( void )
  358. {
  359.     youCount = 0;
  360.     enemyCount = 0;
  361.     shotCount = 0;
  362.     gYouHasGone = FALSE;
  363.     
  364.     GridInit ( enemy );
  365.     GridInit ( you );
  366.     SetPort ( enemyWindow );
  367.     DrawDots ( enemy );
  368.     SetPort ( youWindow );
  369.     DrawDots ( you );
  370.     PlaceEnemyShips ();
  371.     
  372.     SelectWindow ( youWindow );
  373.     SetPort ( youWindow );
  374.     
  375.     PlaceAShip ( kCarrierMin, kCarrierMax, kHorizCarrierID, 'C' );
  376.     PlaceAShip ( kBattleshipMin, kBattleshipMax, kHorizBattleshipID, 'B' );
  377.     PlaceAShip ( kCruiserMin, kCruiserMax, kHorizCruiserID, 'R' );
  378.     PlaceAShip ( kSubMin, kSubMax, kHorizSubID, 'S' );
  379.     PlaceAShip ( kDestroyerMin, kDestroyerMax, kHorizDestroyerID, 'D' );
  380.  
  381.     SelectWindow ( enemyWindow );
  382.     SetPort ( enemyWindow );
  383. }
  384.  
  385. /**************/
  386. /* PlaceAShip */
  387. /**************/
  388.  
  389. void    PlaceAShip ( int theMin, int theMax, int theHorizID, char theLetter )
  390. {
  391.     EventRecord            event;
  392.     Point                thePoint, tempPoint, oldPoint;
  393.     Rect                theRect, tempRect, oldRect;
  394.     char                theChar;
  395.     Boolean                horiz = TRUE, oldHoriz = TRUE;
  396.     
  397.     do /* gets a random temp point for the placement of the first ship */
  398.     {
  399.         tempPoint.v = Randomize ();
  400.         tempPoint.h = Randomize ();
  401.         
  402.         Inbounds ( &tempPoint, horiz, theMin, theMax );
  403.  
  404.     } while ( !ItFits ( horiz, tempPoint, theMin, theMax ) );
  405.     
  406.     PtToShipRect ( tempPoint, &oldRect, horiz, theMin, theMax );
  407.     PtToRect ( tempPoint, &tempRect );
  408.     oldPoint = tempPoint;
  409.     
  410.     DrawShipPart ( theHorizID, oldRect );
  411.     
  412.     while ( !Button () )
  413.     {
  414.         GetMouse ( &thePoint );
  415.  
  416.         if ( WaitNextEvent ( everyEvent, &event, MAXLONG, nil ) )
  417.         {
  418.             theChar = event.message & charCodeMask;
  419.             if ( theChar == 'm' )
  420.                 horiz = !horiz;
  421.         }
  422.         
  423.         tempPoint.v = thePoint.v / kPixelSize;
  424.         tempPoint.h = thePoint.h / kPixelSize;
  425.         
  426.         /* This is really long.  If someone can shorten it, I would appreciate it. */
  427.         if (         ( !PtInRect ( thePoint, &tempRect ) ) &&
  428.                     ( Inbounds ( &tempPoint, horiz, theMin, theMax ) ) && 
  429.                     ( ItFits ( horiz, tempPoint, theMin, theMax ) ) && 
  430.                     ( ( oldPoint.h != tempPoint.h ) || ( oldPoint.v != tempPoint.v ) ) || 
  431.                     ( ( oldHoriz != horiz ) &&
  432.                     ( Inbounds ( &tempPoint, horiz, theMin, theMax ) ) &&
  433.                     ( ItFits ( horiz, tempPoint, theMin, theMax ) ) ) )
  434.         {
  435.             EraseShipPart ( oldRect );
  436.             
  437.             if ( oldHoriz )
  438.                 DrawHorizDots ( oldPoint, tempPoint, &theRect, theMin, theMax );
  439.             else
  440.                 DrawVertDots ( oldPoint, tempPoint, &theRect, theMin, theMax );
  441.             
  442.             PtToShipRect ( tempPoint, &tempRect, horiz, theMin, theMax );
  443.             if ( horiz )
  444.                 DrawShipPart ( theHorizID, tempRect );
  445.             else
  446.                 DrawShipPart ( theHorizID + 1, tempRect );
  447.     
  448.             PtToShipRect ( tempPoint, &oldRect, horiz, theMin, theMax );
  449.             PtToRect ( tempPoint, &tempRect );
  450.             oldPoint = tempPoint;
  451.             oldHoriz = horiz;
  452.         }
  453.         else if ( horiz != oldHoriz )
  454.             horiz = oldHoriz;
  455.     }
  456.     
  457.     SetShipToGrid ( you, oldPoint, horiz, theMin, theMax, theLetter );
  458.     
  459.     while ( Button () );
  460. }
  461.  
  462. /**********/
  463. /* ItFits */
  464. /**********/
  465.  
  466. Boolean    ItFits ( Boolean horiz, Point thePoint, int theMin, int theMax )
  467. {
  468.     Boolean fits = FALSE;
  469.     
  470.     if  ( horiz )
  471.         fits = FitsHoriz ( you, thePoint.h - theMin, thePoint.v, 1 + theMin + theMax );
  472.     else
  473.         fits = FitsVert ( you, thePoint.h, thePoint.v - theMin, 1 + theMin + theMax );
  474.         
  475.     return ( fits );
  476. }
  477.  
  478. /*****************/
  479. /* DrawHorizDots */
  480. /*****************/
  481.  
  482. void    DrawHorizDots ( Point aPoint, Point tempPoint, Rect *theRect, int min, int max )
  483. {
  484.     int i = aPoint.h;
  485.     
  486.     for ( aPoint.h = i - min; aPoint.h <= i + max; aPoint.h++ ) 
  487.     {
  488.         /* PtToDotRect ( aPoint, theRect ); */
  489.         (*theRect).left = ( aPoint.h + 1 ) * 19 - 10;
  490.         (*theRect).top = ( aPoint.v + 1 ) * 19 - 10;
  491.         (*theRect).right = ( aPoint.h + 1 ) * 19;
  492.         (*theRect).bottom = ( aPoint.v + 1 ) * 19;
  493.         
  494.         DrawOneDot ( you[aPoint.h][tempPoint.v].hitOrMiss, theRect );
  495.     }
  496.     
  497. }
  498.  
  499. /****************/
  500. /* DrawVertDots */
  501. /****************/
  502.  
  503. void    DrawVertDots ( Point aPoint, Point tempPoint, Rect *theRect, int min, int max )
  504. {
  505.     int i = aPoint.v;
  506.     
  507.     for ( aPoint.v = i - min; aPoint.v <= i + max; aPoint.v++ )
  508.     {
  509.         /* PtToDotRect ( aPoint, theRect ); */
  510.         (*theRect).left = ( aPoint.h + 1 ) * 19 - 10;
  511.         (*theRect).top = ( aPoint.v + 1 ) * 19 - 10;
  512.         (*theRect).right = ( aPoint.h + 1 ) * 19;
  513.         (*theRect).bottom = ( aPoint.v + 1 ) * 19;
  514.         
  515.         DrawOneDot ( you[tempPoint.h][aPoint.v].hitOrMiss, theRect );
  516.     }
  517.     
  518. }
  519.  
  520. /***************/
  521. /* PtToDotRect */
  522. /***************/
  523.  
  524. void    PtToDotRect ( Point aPoint, Rect *aRect )
  525. {
  526.     (*aRect).left = ( aPoint.h + 1 ) * 19 - 10;
  527.     (*aRect).top = ( aPoint.v + 1 ) * 19 - 10;
  528.     (*aRect).right = ( aPoint.h + 1 ) * 19;
  529.     (*aRect).bottom = ( aPoint.v + 1 ) * 19;
  530. }
  531.  
  532. /************/
  533. /* PtToRect */
  534. /************/
  535.  
  536. void    PtToRect ( Point aPoint, Rect *aRect )
  537. {
  538.     (*aRect).left = ( aPoint.h + 1 ) * 19 - 16;
  539.     (*aRect).top = ( aPoint.v + 1 ) * 19 - 16;
  540.     (*aRect).right = ( aPoint.h + 1 ) * 19 + 6;
  541.     (*aRect).bottom = ( aPoint.v + 1 ) * 19 + 6;
  542. }
  543.  
  544. /****************/
  545. /* PtToShipRect */
  546. /****************/
  547.  
  548. void    PtToShipRect ( Point aPoint, Rect *aRect, Boolean horiz, int min, int max )
  549. {
  550.     if ( horiz )
  551.     {
  552.         (*aRect).left = ( aPoint.h + 1 ) * 19 - 10 - ( kPixelSize * min );
  553.         (*aRect).top = ( aPoint.v + 1 ) * 19 - 10;
  554.         (*aRect).right = ( aPoint.h + 1 ) * 19 + ( kPixelSize * max );
  555.         (*aRect).bottom = ( aPoint.v + 1 ) * 19;
  556.     }
  557.     else
  558.     {
  559.         (*aRect).left = ( aPoint.h + 1 ) * 19 - 10;
  560.         (*aRect).top = ( aPoint.v + 1 ) * 19 - 10 - ( kPixelSize * min );
  561.         (*aRect).right = ( aPoint.h + 1 ) * 19;
  562.         (*aRect).bottom = ( aPoint.v + 1 ) * 19 + ( kPixelSize * max );
  563.     }
  564. }
  565.  
  566. /*****************/
  567. /* SetShipToGrid */
  568. /*****************/
  569. /* purpose: This function takes the current location of the ship upon a mouse down
  570. /*             and puts it into the grid.
  571. /* variables: The grid to set it to; the point of the current mouse location
  572. /*            after it has been translated to the grid coordinates; the vertical
  573. /*            or horizontal orientation of the ship; the minimum grid point that the
  574. /*            ship is at; the maximum grid point that the ship is at; the character
  575. /*            type of the ship.
  576.  */
  577.  
  578. void    SetShipToGrid ( Grid theGrid[][kGridSize], Point tempPoint, 
  579.                             Boolean horiz, int min, int max, char c )
  580. {
  581.     int i;
  582.     
  583.     if ( horiz )
  584.     {
  585.         if ( ( c == 'C' ) || ( c == 'B' ) || ( c == 'D' ) || ( c == 'R' ) )
  586.             theGrid[tempPoint.h - min][tempPoint.v].shipResID = 133;
  587.         else
  588.             theGrid[tempPoint.h - min][tempPoint.v].shipResID = 134;
  589.         
  590.         theGrid[tempPoint.h - 2][tempPoint.v].shipType = c;
  591.         
  592.         for ( i = tempPoint.h - ( min - 1 ); i <= tempPoint.h + ( max - 1 ); i++ )
  593.         {
  594.             theGrid[i][tempPoint.v].shipResID = 135;
  595.             theGrid[i][tempPoint.v].shipType = c;
  596.         }
  597.         
  598.         if ( ( c == 'S' ) || ( c == 'R' ) || ( c == 'D' ) )
  599.             theGrid[tempPoint.h + max][tempPoint.v].shipResID = 136;
  600.         else
  601.             theGrid[tempPoint.h + max][tempPoint.v].shipResID = 137;
  602.  
  603.         theGrid[tempPoint.h + max][tempPoint.v].shipType = c;
  604.     }
  605.     else
  606.     {
  607.         if ( ( c == 'C' ) || ( c == 'B' ) )
  608.             theGrid[tempPoint.h][tempPoint.v - min].shipResID = 138;
  609.         else
  610.             theGrid[tempPoint.h][tempPoint.v - min].shipResID = 139;
  611.         
  612.         theGrid[tempPoint.h][tempPoint.v - 2].shipType = c;
  613.         
  614.         for ( i = tempPoint.v - ( min - 1 ); i <= tempPoint.v + ( max - 1 ); i++ )
  615.         {
  616.             theGrid[tempPoint.h][i].shipResID = 140;
  617.             theGrid[tempPoint.h][i].shipType = c;
  618.         }
  619.         
  620.         if ( c == 'S' )
  621.             theGrid[tempPoint.h][tempPoint.v + max].shipResID = 141;
  622.         else
  623.             theGrid[tempPoint.h][tempPoint.v + max].shipResID = 142;
  624.         
  625.         theGrid[tempPoint.h][tempPoint.v + 2].shipType = c;
  626.     }
  627. }
  628.  
  629. /************/
  630. /* DrawDots */
  631. /************/
  632.  
  633. void    DrawDots ( Grid theGrid[][kGridSize] )
  634. {
  635.     Rect        pictureRect;
  636.     WindowPtr    window;
  637.     PicHandle    hitDot, missDot, nullDot;
  638.     int            i, j, windowSize;
  639.     Boolean        isYou = FALSE;
  640.     
  641.     if ( theGrid == you )
  642.         isYou = TRUE;
  643.     
  644.     window = FrontWindow ();
  645.     windowSize = window->portRect.right - window->portRect.left;
  646.  
  647.     EraseRect ( &window->portRect );
  648.     
  649.     if ( useColor )
  650.     {
  651.         hitDot = GetPicture ( kHitDotID );
  652.         if ( hitDot == nil )
  653.         {
  654.             SysBeep ( 10 );
  655.             ExitToShell ();
  656.         }
  657.     }
  658.     else
  659.     {
  660.         hitDot = GetPicture ( kBWHitDotID );
  661.         if ( hitDot == nil )
  662.         {
  663.             SysBeep ( 10 );
  664.             ExitToShell ();
  665.         }
  666.     }
  667.  
  668.     missDot = GetPicture ( kMissDotID );
  669.     if ( missDot == nil )
  670.     {
  671.         SysBeep ( 10 );
  672.         ExitToShell ();
  673.     }
  674.  
  675.     nullDot = GetPicture ( kNullDotID );
  676.     if ( nullDot == nil )
  677.     {
  678.         SysBeep ( 10 );
  679.         ExitToShell ();
  680.     }
  681.     
  682.     i = 0;
  683.     for ( i; i <= 9; i++ )
  684.     {
  685.         j = 0;
  686.         for ( j; j <= 9; j++ )
  687.         {
  688.             pictureRect.left = ( i + 1 ) * 19 - 10;
  689.             pictureRect.top = ( j + 1 ) * 19 - 10;
  690.             pictureRect.right = ( i + 1 ) * 19;
  691.             pictureRect.bottom = ( j + 1 ) * 19;
  692.             
  693.             if ( isYou && ( theGrid[i][j].shipResID != 0 ) )
  694.                 DrawShipPart ( theGrid[i][j].shipResID, pictureRect );
  695.             else if ( ( ( enemyCount >= 17 ) || ( youCount >= 17 ) ) &&
  696.                             ( theGrid[i][j].shipResID != 0 ) )
  697.                 DrawShipPart ( theGrid[i][j].shipResID, pictureRect );
  698.             
  699.             if ( theGrid[i][j].hitOrMiss == hit )
  700.                 DrawPicture ( hitDot, &pictureRect );
  701.             else if ( theGrid[i][j].hitOrMiss == miss )
  702.                 DrawPicture ( missDot, &pictureRect );
  703.             else
  704.                 DrawPicture ( nullDot, &pictureRect );
  705.         }
  706.     }
  707. }
  708.  
  709. /****************/
  710. /* DrawShipPart */
  711. /****************/
  712.  
  713. void    DrawShipPart ( int resID, Rect pictureRect )
  714. {
  715.     PicHandle    picture;
  716.  
  717.     pictureRect.left -= 3;
  718.     pictureRect.top -= 3;
  719.     pictureRect.right += 3;
  720.     pictureRect.bottom += 3;
  721.             
  722.     picture = GetPicture ( resID );
  723.     if ( picture == nil )
  724.     {
  725.         SysBeep ( 10 );
  726.         ExitToShell ();
  727.     }
  728.  
  729.     DrawPicture ( picture, &pictureRect );
  730. }
  731.  
  732. /*****************/
  733. /* EraseShipPart */
  734. /*****************/
  735.  
  736. void    EraseShipPart ( Rect pictureRect )
  737. {
  738.     pictureRect.left -= 3;
  739.     pictureRect.top -= 3;
  740.     pictureRect.right += 3;
  741.     pictureRect.bottom += 3;
  742.             
  743.     EraseRect ( &pictureRect );
  744. }
  745.  
  746. /************/
  747. /* GridInit */
  748. /************/
  749.  
  750. void    GridInit ( Grid aGrid[][kGridSize] )
  751. {
  752.     int        i, j;
  753.     
  754.     for ( i = 0; i < kGridSize; i++ )
  755.     {
  756.         for ( j = 0; j < kGridSize; j++ )
  757.         {
  758.             aGrid[i][j].shipType = ' ';
  759.             aGrid[i][j].shipResID = 0;
  760.             aGrid[i][j].hitOrMiss = noTry;
  761.         }
  762.     }
  763. }
  764.  
  765. /*******************/
  766. /* PlaceEnemyShips */
  767. /*******************/
  768.  
  769. void    PlaceEnemyShips ( void )
  770. {
  771.     int        s;
  772.     
  773.     GetDateTime( &randSeed );
  774.     
  775.     GridInit ( enemy );
  776.  
  777.     PlaceAnEnemyShip ( kCarrierSize, kCarrierMin, kCarrierMax, 'C' );
  778.     PlaceAnEnemyShip ( kBattleshipSize, kBattleshipMin, kBattleshipMax, 'B' );
  779.     PlaceAnEnemyShip ( kCruiserSize, kCruiserMin, kCruiserMax, 'R' );
  780.     PlaceAnEnemyShip ( kSubSize, kSubMin, kSubMax, 'S' );
  781.     PlaceAnEnemyShip ( kDestroyerSize, kDestroyerMin, kDestroyerMax, 'D' );
  782. }
  783.  
  784. /********************/
  785. /* PlaceAnEnemyShip */
  786. /********************/
  787.  
  788. void    PlaceAnEnemyShip ( int shipSize, int min, int max, char c )
  789. {
  790.     Boolean                ItDoesntFit = TRUE, horiz;
  791.     int                 dir;
  792.     Point                aPoint;
  793.     
  794.     while ( ItDoesntFit )
  795.     {
  796.         aPoint.h = Randomize ();
  797.         aPoint.v = Randomize ();
  798.         
  799.         dir = Randomize ();
  800.         
  801.         if ( ( ( float ) dir / 2 ) == ( dir / 2 ) )       /* It's even so horizontal */
  802.         {
  803.             if ( ( aPoint.h <= 10 - shipSize ) && ( aPoint.h >= 0 ) && 
  804.                         ( FitsHoriz ( enemy, aPoint.h, aPoint.v, shipSize ) ) )
  805.             {
  806.                 horiz = TRUE;
  807.                 aPoint.h += min;
  808.                 SetShipToGrid ( enemy, aPoint, horiz, min, max, c );
  809.                 ItDoesntFit = FALSE;
  810.             }
  811.         }
  812.         else                                            /* It's odd so vertical */
  813.         {
  814.             if ( ( aPoint.v <= 10 - shipSize ) && ( aPoint.v >= 0 ) && 
  815.                         ( FitsVert ( enemy, aPoint.h, aPoint.v, shipSize ) ) )
  816.             {
  817.                 horiz = FALSE;
  818.                 aPoint.v += min;
  819.                 SetShipToGrid ( enemy, aPoint, horiz, min, max, c );
  820.                 ItDoesntFit = FALSE;
  821.             }
  822.         }
  823.     }
  824. }
  825.  
  826. /************/
  827. /* FitsVert */
  828. /************/
  829.  
  830. Boolean    FitsVert ( Grid theGrid[][kGridSize], int x, int y, int shipSize )
  831. {
  832.     Boolean fits = TRUE;
  833.     int        i;
  834.     
  835.     for ( i = y; i < y + shipSize; i++ )
  836.     {
  837.         if ( theGrid[x][i].shipResID != 0 )
  838.             fits = FALSE;
  839.     }
  840.     return ( fits );
  841. }
  842.  
  843. /*************/
  844. /* FitsHoriz */
  845. /*************/
  846.  
  847. Boolean    FitsHoriz ( Grid theGrid[][kGridSize], int x, int y, int shipSize )
  848. {
  849.     Boolean fits = TRUE;
  850.     int        i;
  851.     
  852.     for ( i = x; i < x + shipSize; i++ )
  853.     {
  854.         if ( theGrid[i][y].shipResID != 0 )
  855.             fits = FALSE;
  856.     }
  857.     return ( fits );
  858. }
  859.  
  860. /*************/
  861. /* Randomize */
  862. /*************/
  863.  
  864. int        Randomize ( void )
  865. {
  866.     long    randomNumber;
  867.     
  868.     randomNumber = Random ();
  869.     
  870.     if ( randomNumber < 0 )
  871.         randomNumber *= -1;
  872.     
  873.     if ( randomNumber == 0 )
  874.         return ( randomNumber );
  875.     else
  876.         return ( ( ( randomNumber * kRandomRange ) / kRandomUpperLimit ) );
  877. }
  878.  
  879. /**************/
  880. /* CheckPoint */
  881. /**************/
  882.  
  883. void    CheckPoint ( Point mouseLocal )
  884. {
  885.     Rect        dotRect;
  886.     Point        mouseCopy;
  887.     Handle        mySndHandle;
  888.     
  889.     GlobalToLocal ( &mouseLocal );
  890.     mouseCopy = mouseLocal;
  891.     
  892.     if ( mouseLocal.v == 200 )
  893.         mouseLocal.v = 9;
  894.     else
  895.         mouseLocal.v /= kPixelSize;
  896.     if ( mouseLocal.h == 200 )
  897.         mouseLocal.h = 9;
  898.     else
  899.         mouseLocal.h /= kPixelSize;
  900.     
  901.     PtToDotRect ( mouseLocal, &dotRect );
  902.             
  903.     if ( ( PtInRect ( mouseCopy, &dotRect ) ) &&
  904.                  ( enemy[mouseLocal.h][mouseLocal.v].hitOrMiss != hit ) && 
  905.                 ( enemy[mouseLocal.h][mouseLocal.v].hitOrMiss != miss ) )
  906.     {
  907.         if ( gHasSound )
  908.         {
  909.             mySndHandle = GetResource ( 'snd ', kBombDropSnd );
  910.             SndPlay ( nil, mySndHandle, TRUE );
  911.         }
  912.         
  913.         if ( enemy[mouseLocal.h][mouseLocal.v].shipResID == 0 )
  914.         {
  915.             enemy[mouseLocal.h][mouseLocal.v].hitOrMiss = miss;
  916.             DrawOneDot ( kMissDotID, &dotRect );
  917.         
  918.             if ( gHasSound )
  919.             {
  920.                 mySndHandle = GetResource ( 'snd ', kSplashSnd );
  921.                 SndPlay ( nil, mySndHandle, TRUE );
  922.             }
  923.         }
  924.         else
  925.         {
  926.             enemy[mouseLocal.h][mouseLocal.v].hitOrMiss = hit;
  927.             DrawOneDot ( kHitDotID, &dotRect );
  928.  
  929.             if ( gHasSound )
  930.             {
  931.                 mySndHandle = GetResource ( 'snd ', kExplosionSnd );
  932.                 SndPlay ( nil, mySndHandle, TRUE );
  933.             }
  934.             
  935.             enemyCount++;
  936.         }
  937.         
  938.         gYouHasGone = TRUE;
  939.     }
  940. }
  941.  
  942. /**************/
  943. /* DrawOneDot */
  944. /**************/
  945.  
  946. void    DrawOneDot ( int dotID, Rect *dotRect )
  947. {
  948.     PicHandle    picture;
  949.     
  950.     picture = GetPicture ( dotID );
  951.     if ( picture == nil )
  952.     {
  953.         SysBeep ( 10 );
  954.         ExitToShell ();
  955.     }
  956.     DrawPicture ( picture, dotRect );
  957. }
  958.  
  959. /************/
  960. /* Inbounds */
  961. /************/
  962.  
  963. Boolean    Inbounds ( Point *tempPoint, Boolean horiz, int min, int max )
  964. {
  965.     Boolean    vTest = TRUE;
  966.     Boolean hTest = TRUE;
  967.     
  968.     if ( horiz )
  969.     {
  970.         if ( (*tempPoint).h < min )
  971.         {
  972.             (*tempPoint).h = min;
  973.             hTest = FALSE;
  974.         }
  975.         if ( (*tempPoint).h > ( 9 - max ) )
  976.         {
  977.             (*tempPoint).h = ( 9 - max );
  978.             hTest = FALSE;
  979.         }
  980.         if ( (*tempPoint).v < 0 )
  981.         {
  982.             (*tempPoint).v = 0;
  983.             vTest = FALSE;
  984.         }
  985.         if ( (*tempPoint).v > 9 )
  986.         {
  987.             (*tempPoint).v = 9;
  988.             vTest = FALSE;
  989.         }
  990.     }
  991.     
  992.     else
  993.     {
  994.         if ( (*tempPoint).v < min )
  995.         {
  996.             (*tempPoint).v = min;
  997.             hTest = FALSE;
  998.         }
  999.         if ( (*tempPoint).v > ( 9 - max ) )
  1000.         {
  1001.             (*tempPoint).v = ( 9 - max );
  1002.             hTest = FALSE;
  1003.         }
  1004.         if ( (*tempPoint).h < 0 )
  1005.         {
  1006.             (*tempPoint).h = 0;
  1007.             vTest = FALSE;
  1008.         }
  1009.         if ( (*tempPoint).h > 9 )
  1010.         {
  1011.             (*tempPoint).h = 9;
  1012.             vTest = FALSE;
  1013.         }
  1014.     }
  1015.         
  1016.     if ( ( hTest == FALSE ) && ( vTest == FALSE ) )
  1017.         return ( FALSE );
  1018.     else
  1019.         return ( TRUE );
  1020. }
  1021.  
  1022. /*****************/
  1023. /* PickEnemyShot */
  1024. /*****************/
  1025.  
  1026. void    PickEnemyShot ( void )
  1027. {
  1028.     Rect                theRect;
  1029.     
  1030.     static cond            lastTry = miss;
  1031.     static Point        lastPoint =  {0,0}, firstHitPoint  = {0,0};
  1032.     static Boolean        keepTrying = FALSE, isHorizontal = FALSE, hitsYet = FALSE;
  1033.     static Direction    lastDir = right;
  1034.     static Point        thisPoint = {0,0};
  1035.     
  1036.     if ( !youCount )
  1037.     {
  1038.         lastTry = miss;
  1039.         keepTrying = FALSE;
  1040.         isHorizontal = FALSE;
  1041.         hitsYet = FALSE;
  1042.         lastDir = right;
  1043.     }
  1044.  
  1045.     if ( keepTrying == TRUE )
  1046.     {
  1047.         if ( ( lastDir == right ) && ( thisPoint.h < 9 ) )
  1048.         {
  1049.             thisPoint.h++;
  1050.             
  1051.             if ( you[thisPoint.h][thisPoint.v].hitOrMiss == noTry )
  1052.             {
  1053.                 lastTry = PlaceTheShot ( thisPoint );
  1054.                 
  1055.                 if ( lastTry == miss )
  1056.                 {
  1057.                     thisPoint = firstHitPoint;
  1058.                     lastDir = left;
  1059.                 }
  1060.                 
  1061.                 if ( lastTry ==  hit )
  1062.                 {
  1063.                     lastPoint = thisPoint;
  1064.                     hitsYet = TRUE;
  1065.                     isHorizontal = TRUE;
  1066.                 }
  1067.                 return;
  1068.             }
  1069.             else
  1070.             {
  1071.                 thisPoint = firstHitPoint;
  1072.                 lastDir = left;
  1073.             }
  1074.         }
  1075.         else if ( ( lastDir == right ) && ( ( isHorizontal ) || ( thisPoint.h == 9 ) ) )
  1076.         {
  1077.             thisPoint = firstHitPoint;
  1078.             lastDir = left;
  1079.         }
  1080.         
  1081.         if ( ( lastDir == left ) && ( thisPoint.h > 0 ) )
  1082.         {
  1083.             thisPoint.h--;
  1084.             
  1085.             if ( you[thisPoint.h][thisPoint.v].hitOrMiss == noTry )
  1086.             {
  1087.                 lastTry = PlaceTheShot ( thisPoint );
  1088.                 
  1089.                 switch ( lastTry )
  1090.                 {
  1091.                     case hit:
  1092.                         lastPoint = thisPoint;
  1093.                         isHorizontal = TRUE;
  1094.                         hitsYet = TRUE;
  1095.                         break;
  1096.  
  1097.                     case miss:
  1098.                         if ( hitsYet )
  1099.                         {
  1100.                             keepTrying = FALSE;
  1101.                             lastDir = right;
  1102.                             hitsYet = FALSE;
  1103.                         }
  1104.                         else
  1105.                         {
  1106.                             thisPoint = firstHitPoint;
  1107.                             lastDir = up;
  1108.                         }
  1109.                         break;
  1110.                 }
  1111.                     
  1112.                 return;
  1113.             }
  1114.             else
  1115.             {
  1116.                 if  ( hitsYet )
  1117.                 {
  1118.                     lastDir = right;
  1119.                     keepTrying = FALSE;
  1120.                     hitsYet = FALSE;
  1121.                 }
  1122.                 else
  1123.                 {
  1124.                     thisPoint = firstHitPoint;
  1125.                     lastDir = up;
  1126.                 }
  1127.             }
  1128.         }
  1129.         else if ( ( isHorizontal ) || ( lastDir == left ) )
  1130.         {
  1131.             if  ( hitsYet )
  1132.             {
  1133.                 lastDir = right;
  1134.                 keepTrying = FALSE;
  1135.                 hitsYet = FALSE;
  1136.             }
  1137.             else
  1138.             {
  1139.                 lastDir = up;
  1140.             }
  1141.         }
  1142.  
  1143.         if ( ( lastDir == up ) && ( thisPoint.v > 0 ) )
  1144.         {
  1145.             thisPoint.v--;
  1146.             
  1147.             if ( you[thisPoint.h][thisPoint.v].hitOrMiss == noTry )
  1148.             {
  1149.                 lastTry = PlaceTheShot ( thisPoint );
  1150.                 
  1151.                 if ( lastTry == miss )
  1152.                 {
  1153.                     thisPoint = firstHitPoint;
  1154.                     lastDir = down;
  1155.                 }
  1156.                 
  1157.                 if ( lastTry ==  hit )
  1158.                 {
  1159.                     lastPoint = thisPoint;
  1160.                     hitsYet = TRUE;
  1161.                 }
  1162.                 return;
  1163.             }
  1164.             else
  1165.             {
  1166.                 thisPoint = firstHitPoint;
  1167.                 lastDir = down;
  1168.             }
  1169.         }
  1170.         else if ( ( !isHorizontal ) && (lastDir == up ) )
  1171.         {
  1172.             lastDir = down;
  1173.             thisPoint = firstHitPoint;
  1174.         }
  1175.         
  1176.         if ( ( lastDir == down ) && ( thisPoint.v < 9 ) )
  1177.         {
  1178.             thisPoint.v++;
  1179.             
  1180.             if ( you[thisPoint.h][thisPoint.v].hitOrMiss == noTry )
  1181.             {
  1182.                 lastTry = PlaceTheShot ( thisPoint );
  1183.                 
  1184.                 if ( lastTry == miss )
  1185.                 {
  1186.                     if ( hitsYet )
  1187.                     {
  1188.                         keepTrying = FALSE;
  1189.                         lastDir = right;
  1190.                         hitsYet = FALSE;
  1191.                     }
  1192.                     else
  1193.                     {
  1194.                         lastPoint = thisPoint;
  1195.                         lastDir = up;
  1196.                     }
  1197.                 }
  1198.                 
  1199.                 if ( lastTry == hit )
  1200.                 {
  1201.                     hitsYet = TRUE;
  1202.                 }
  1203.                     
  1204.                 return;
  1205.             }
  1206.             else
  1207.             {
  1208.                 lastDir = right;
  1209.                 hitsYet = FALSE;
  1210.             }
  1211.         }
  1212.         else if ( !isHorizontal )
  1213.         {
  1214.             lastDir = right;
  1215.             hitsYet = FALSE;
  1216.             keepTrying  = FALSE;
  1217.         }
  1218.     }
  1219.  
  1220.     do
  1221.     {
  1222.         do
  1223.         {
  1224.             thisPoint.h = Randomize ();
  1225.         } while ( ( thisPoint.h < 0 ) || ( thisPoint.h > 9 ) );
  1226.         do
  1227.         {
  1228.             thisPoint.v = Randomize ();
  1229.         } while ( ( thisPoint.v < 0 ) || ( thisPoint.v > 9 ) );
  1230.     }  while ( IsBadRandom ( thisPoint, shotCount < kMinSpacedShots ) );
  1231.     
  1232.     lastTry = PlaceTheShot ( thisPoint );
  1233.     
  1234.     if ( lastTry == hit )
  1235.     {
  1236.         firstHitPoint = thisPoint;
  1237.         keepTrying = TRUE;
  1238.     }
  1239.     else
  1240.         keepTrying = FALSE;
  1241.     
  1242.     lastDir = right;
  1243.     lastPoint = thisPoint;
  1244.     isHorizontal = FALSE;
  1245.     
  1246.     return;
  1247. }
  1248.  
  1249. /***************/
  1250. /* IsBadRandom */
  1251. /***************/
  1252.  
  1253. Boolean    IsBadRandom ( Point thePoint, Boolean canCheck )
  1254. {
  1255.     Point    tempPoint = thePoint;
  1256.     
  1257.     if ( ( you[thePoint.h][thePoint.v].hitOrMiss == hit ) ||
  1258.                 ( you[thePoint.h][thePoint.v].hitOrMiss == miss ) )
  1259.         return ( TRUE );
  1260.     
  1261.     if ( canCheck ) /* After a certain number of tries which is #define, 
  1262.                         this will be false.  It prevents having random
  1263.                         guesses next to each other early in the game. */
  1264.     {
  1265.         if ( thePoint.h > 0 )
  1266.         {
  1267.             if ( ( you[thePoint.h - 1][thePoint.v].hitOrMiss == hit ) ||
  1268.                         ( you[thePoint.h - 1][thePoint.v].hitOrMiss == miss ) )
  1269.                 return ( TRUE );
  1270.         }
  1271.         if ( thePoint.h < 9 )
  1272.         {
  1273.             if ( ( you[thePoint.h + 1][thePoint.v].hitOrMiss == hit ) ||
  1274.                         ( you[thePoint.h + 1][thePoint.v].hitOrMiss == miss ) )
  1275.                 return ( TRUE );
  1276.         }
  1277.         if ( thePoint.v > 0 )
  1278.         {
  1279.             if ( ( you[thePoint.h][thePoint.v-1].hitOrMiss == hit ) ||
  1280.                         ( you[thePoint.h][thePoint.v-1].hitOrMiss == miss ) )
  1281.                 return ( TRUE );
  1282.         }
  1283.         if ( thePoint.v < 9 )
  1284.         {
  1285.             if ( ( you[thePoint.h][thePoint.v+1].hitOrMiss == hit ) ||
  1286.                         ( you[thePoint.h][thePoint.v+1].hitOrMiss == miss ) )
  1287.                 return ( TRUE );
  1288.         }
  1289.     }
  1290.     
  1291.     /* If the point is surrounded by white on all sides, why guess there? */
  1292.     if ( ( you[thePoint.h - 1][thePoint.v].hitOrMiss == miss ) && 
  1293.             ( you[thePoint.h + 1][thePoint.v].hitOrMiss == miss ) &&
  1294.             ( you[thePoint.h][thePoint.v - 1].hitOrMiss == miss ) &&
  1295.             ( you[thePoint.h][thePoint.v + 1].hitOrMiss == miss ) )
  1296.         return ( TRUE );
  1297.     
  1298.     return ( FALSE );
  1299. }
  1300.  
  1301. /****************/
  1302. /* PlaceTheShot */
  1303. /****************/
  1304.  
  1305. cond    PlaceTheShot ( Point thePoint )
  1306. {
  1307.     Rect  theRect;
  1308.     Handle        mySndHandle;
  1309.     
  1310.     SetPort ( youWindow );
  1311.     
  1312.     if ( gHasSound )
  1313.     {
  1314.         mySndHandle = GetResource ( 'snd ', kBombDropSnd );
  1315.         SndPlay ( nil, mySndHandle, TRUE );
  1316.     }
  1317.     
  1318.     if ( you[thePoint.h][thePoint.v].shipResID != 0 )
  1319.     {
  1320.         you[thePoint.h][thePoint.v].hitOrMiss = hit;
  1321.         
  1322.         if ( gHasSound )
  1323.         {
  1324.             mySndHandle = GetResource ( 'snd ', kExplosionSnd );
  1325.             SndPlay ( nil, mySndHandle, TRUE );
  1326.         }
  1327.         
  1328.         youCount++;
  1329.     }
  1330.     else
  1331.     {
  1332.         you[thePoint.h][thePoint.v].hitOrMiss = miss;
  1333.         
  1334.         if ( gHasSound )
  1335.         {
  1336.             mySndHandle = GetResource ( 'snd ', kSplashSnd );
  1337.             SndPlay ( nil, mySndHandle, TRUE );
  1338.         }
  1339.     }
  1340.     
  1341.     PtToDotRect ( thePoint, &theRect );
  1342.     DrawOneDot ( you[thePoint.h][thePoint.v].hitOrMiss, &theRect );
  1343.     
  1344.     shotCount++;
  1345.     
  1346.     return ( you[thePoint.h][thePoint.v].hitOrMiss );
  1347. }
  1348.  
  1349. /************/
  1350. /* IsColour */
  1351. /************/
  1352.  
  1353. Boolean    IsColour( void )
  1354. {
  1355.     SysEnvRec        mySE;
  1356.     
  1357.     /* Check to see if colour quickdraw is installed */
  1358.     SysEnvirons( 2, &mySE );
  1359.     return( mySE.hasColorQD );
  1360. }
  1361.     
  1362.